//---------------------------------------------------------------------------
// Name:	Meteor.cpp
// Desc:	Source of CMeteor
// Author:	D.C
// Date:	2007-9-19 10:03:11
//---------------------------------------------------------------------------
#include <commdb.h>
#include <nifman.h>
#include "cmeteor.h"

#include "elog.h"

CMeteor* CMeteor::NewL(MMeteorNotifier* aNotifier)
{
	CMeteor* self=new (ELeave) CMeteor();
	CleanupStack::PushL(self);
	self->ConstructL(aNotifier);
	CleanupStack::Pop(self);
	return self;
}
void CMeteor::ConstructL(MMeteorNotifier* aNotifier)
{
	m_pNotifier=aNotifier;
	CActiveScheduler::Add(this);
}
CMeteor::CMeteor():CActive(EPriorityStandard)
{
	m_pNotifier=NULL;
	m_pServerHost=NULL;
	m_pHdr=NULL;

	m_iProxyPort=0;
	m_iServerPort=0;
	m_tStatus=TMeteorNotConnected;
	m_bProxyUsed=EFalse;
	m_bIsGRPS=ETrue;
}

CMeteor::~CMeteor()
{
	Disconnect();

	m_pNotifier=NULL;

	SAFE_DELETE( m_pServerHost );
	SAFE_DELETE( m_pHdr );

	m_iProxyPort=0;
	m_iServerPort=0;
	m_tStatus=TMeteorNotConnected;
}

TInt CMeteor::Connect(const TDesC& aHost,TInt aPort,TUint32 aIAP)
{
	if (m_bIsWorking)
	{
		return KErrNotReady;
	}
	m_iIAP=aIAP;
	SAFE_DELETE(m_pServerHost);
	m_bProxyUsed=EFalse;
	if (KErrNone!=GetProxy(m_iIAP,m_tProxyHost,m_iProxyPort,m_bIsGRPS))
	{
		m_bProxyUsed=EFalse;
		m_pServerHost=aHost.Alloc();
		m_iServerPort=aPort;
	}
	else
	{
		m_bProxyUsed=ETrue;
		m_pServerHost=m_tProxyHost.Alloc();
		m_iServerPort=m_iProxyPort;
	}

	m_tStatus=TMeteorConnStarting;
	TInt ret=m_rSocketServ.Connect();
	if (KErrNone!=ret)
	{
		return ret;
	}
	ret=m_rConnection.Open(m_rSocketServ);
	if (KErrNone!=ret)
	{
		return ret;
	}
	m_tPref.SetIapId(m_iIAP);
	m_tPref.SetDialogPreference(ECommDbDialogPrefDoNotPrompt);
	m_tPref.SetBearerSet(ECommDbBearerPSD);
	m_tPref.SetDirection(ECommDbConnectionDirectionOutgoing);
	iStatus=KRequestPending;
	m_rConnection.Start(m_tPref,iStatus);

	SetActive();
	m_bIsWorking=ETrue;
	return KErrNone;
}

void CMeteor::Disconnect()
{
	if (!m_bIsWorking)
		return;
	m_bIsWorking=EFalse;

	if (IsActive())
	{
		Cancel();
	}
	m_rSocket.Close();
    m_rConnection.Close();
    m_rSocketServ.Close();
	m_tStatus=TMeteorNotConnected;
}
TInt CMeteor::OpenSocket()
{
	if (TMeteorHostLookUpDone!=m_tStatus)
	{
		return KErrNotReady;
	}
	TInt ret=m_rSocket.Open(m_rSocketServ,KAfInet,KSockStream,KProtocolInetTcp,m_rConnection);
	if (ret!=KErrNone)
	{
		CloseSocket();
		return ret;
	}
	else
	{
		TInetAddr addr;
		addr.SetPort(m_iServerPort);
		addr.SetAddress(m_u32Addr);
		iStatus=KRequestPending;
		m_rSocket.Connect(addr,iStatus);
		m_tStatus=TMeteorSocketConnecting;
		SetActive();
	}
	return ret;
}
void CMeteor::CloseSocket()
{
	if (IsActive())
	{
		Cancel();
	}
	m_rSocket.Close();
	m_tStatus=TMeteorHostLookUpDone;
}
TInt CMeteor::Read()
{
	if ((m_tStatus==TMeteorSocketConnectedAndIdle)&&!IsActive())
	{
		m_tReadBuffer.FillZ();
		m_tReadBuffer.Zero();
		m_tNatrueSize()=0;
		iStatus=KRequestPending;
		m_tStatus=TMeteorReading;
		m_rSocket.RecvOneOrMore(m_tReadBuffer,0,iStatus,m_tNatrueSize);
		SetActive();
	}
	else
	{
		return KErrNotReady;
	}
	return KErrNone;
}
TInt CMeteor::Write(const TDesC8& aBuf)
{
	LOOG(_L("CMeteor::Write"));
	LOOG(aBuf);
	SAFE_DELETE( m_pHdr );
	m_pHdr=HBufC8::New(aBuf.Length());
	TPtr8 hdr_ptr(m_pHdr->Des());
	hdr_ptr.Copy(aBuf);
	if (m_tStatus==TMeteorSocketConnectedAndIdle&&!IsActive())
	{
		m_tStatus=TMeteorWriting;
		iStatus=KRequestPending;
		m_rSocket.Write(m_pHdr->Des(),iStatus);
		SetActive();
	}
	else
	{
		return KErrNotReady;
	}
	return KErrNone;
}
void CMeteor::DoCancel()
{
	switch(m_tStatus)
	{
		case TMeteorHostLookingUp:
		{
			m_rResolver.Cancel();
			m_rResolver.Close();
		}
		break;
		case TMeteorSocketConnecting:
		{
			m_rSocket.CancelConnect();
		}
		break;
		case TMeteorWriting:
		{
			m_rSocket.CancelWrite();
		}
		break;
		case TMeteorReading:
		{
			m_rSocket.CancelRead();
		}
		break;
		default:
		{
		}
		break;
	}
}
void CMeteor::RunL()
{
	if (!m_bIsWorking)
		return;
	TInt state=iStatus.Int();
	TInt ret=KErrNone;
	LOOG(_L("CMeteor::RunL:%d,%d"),m_tStatus,state);
	switch(m_tStatus)
	{
		case TMeteorConnStarting:
		{
			if (state==KErrNone||state==KErrAlreadyExists)
			{
				TInetAddr addr;
				ret=addr.Input(m_pServerHost->Des());
				if (ret==KErrNone)
				{
					m_u32Addr=addr.Address();
					m_tStatus=TMeteorHostLookUpDone;
				}
				else
				{
					ret=m_rResolver.Open(m_rSocketServ,KAfInet,KProtocolInetUdp,m_rConnection);
					iStatus=KRequestPending;
					m_rResolver.GetByName(m_pServerHost->Des(),m_tNameEntry,iStatus);
					m_tStatus=TMeteorHostLookingUp;
					SetActive();
					break;
				}
			}
			else
			{
				Cancel();
			}
			if (NULL!=m_pNotifier)
			{
				m_pNotifier->ConnectionComplete(state);
			}
		}
		break;
		case TMeteorHostLookingUp:
		{
			m_rResolver.Close();
			if (state==KErrNone)
			{
				m_u32Addr=TInetAddr::Cast(m_tNameEntry().iAddr).Address();
				m_tStatus=TMeteorHostLookUpDone;
			}
			else
			{
				Cancel();
			}
			if (NULL!=m_pNotifier)
			{
				m_pNotifier->DNSComplete(state);
			}
		}
		break;
		case TMeteorHostLookUpDone:
		{
			if (NULL!=m_pNotifier)
			{
				m_pNotifier->DNSComplete(state);
			}
		}
		break;
		case TMeteorSocketConnecting:
		{
			if (state==KErrNone)
			{
				m_tStatus=TMeteorSocketConnectedAndIdle;
			}
			else
			{
				Cancel();
			}
			if (NULL!=m_pNotifier)
			{
				m_pNotifier->SocketOpenComplete(state);
			}
		}
		break;
		case TMeteorWriting:
		{
			if (state==KErrNone)
			{
				m_tStatus=TMeteorSocketConnectedAndIdle;
			}
			else
			{
				Cancel();
			}
			if (NULL!=m_pNotifier)
			{
				m_pNotifier->WriteBufferComplete(state);
			}
		}
		break;
		case TMeteorReading:
		{
			if (state==KErrNone||state==KErrEof||state==KErrDisconnected)
			{
				m_tStatus=TMeteorSocketConnectedAndIdle;
			}
			else
			{
				Cancel();
			}
			if (NULL!=m_pNotifier)
			{
				TInt i=m_tNatrueSize();
				if ((i<=KReadBufferSize)&&(i!=m_tReadBuffer.Length()))
				{
					m_tReadBuffer.SetLength(i);
				}
				m_pNotifier->ReadBufferComplete(state,m_tReadBuffer);
			}
		}
		break;
		default:
		{
			if (NULL!=m_pNotifier)
			{
				m_pNotifier->UnknowComplete(state);
			}
		}
		break;
	}
}
TInt CMeteor::RunError(TInt aError)
{
	LOOG(_L("CMeteor::RunError(%d)"),aError);
	if (NULL==m_pNotifier)
		return KErrNone;

	switch(m_tStatus)
	{
		case TMeteorConnStarting:
		{
			m_pNotifier->ConnectionComplete(aError);
		}
		break;
		case TMeteorHostLookingUp:
		{
			m_pNotifier->DNSComplete(aError);
		}
		break;
		case TMeteorHostLookUpDone:
		{
			m_pNotifier->DNSComplete(aError);
		}
		break;
		case TMeteorSocketConnecting:
		{
			m_pNotifier->SocketOpenComplete(aError);
		}
		break;
		case TMeteorWriting:
		{
			m_pNotifier->WriteBufferComplete(aError);
		}
		break;
		case TMeteorReading:
		{
			TBufC8<1>err;
			m_pNotifier->ReadBufferComplete(aError,err);
		}
		break;
		default:
		{
			m_pNotifier->UnknowComplete(aError);
		}
		break;
	}
	return KErrNone;
}
TBool CMeteor::ProxyUsed()
{
	return m_bProxyUsed;
}
